#ifndef _OBJECT_
#define _OBJECT_

#include "..\Core\base.h"
#include "hge\hgegui.h"
#include "hge\hgeresource.h"

namespace air {
	class SceneManager;
	class Acc;

	/**
	 * @brief base class for all NON-GUI Object
	 */
	class IObject {
	public:
		friend class Acc;
		IObject(hgeResourceManager* _hgeResMan, HGE* _hge)
			: next(0), prev(0), hgeResMan(_hgeResMan),  hge(_hge) {}
		virtual ~IObject() {}
		/**
		 * @brief release source
		 *
		 * @return whether release successfully
		 */
		virtual void release() {};
		virtual void render() = 0;
		virtual bool update(float dt) { return false;}
		IObject *next, *prev;
	protected:
		Acc* acc;
		hgeResourceManager* hgeResMan;
		HGE* hge;
	};

	/**
	 * @brief base class for all GUI Object
	 */
	class IGuiObject: public hgeGUIObject{
	public:
		/**
		 * @brief set hgeGUIObject default and necessary setting
		 */
		IGuiObject(hgeResourceManager* _hgeResMan): hgeResMan(_hgeResMan), layoutType(0), isPositionUpdate(true)
		{
			bStatic = false;	// responsive to event
			bVisible = true;	// visible
			bEnabled = true;	//what
		}

		/**
		 * @brief set offset to an anchor point. can be either absolute value or proportional value, determined by layoutType.
		 */
		void setLayoutOffset(float _ox, float _oy) { ox = _ox; oy = _oy; }
		/**
		 * @brief return vertical offset from anchor point. can be either absolute or proportional
		 */
		float getVerticalOffset() const { return oy; }
		/**
		 * @brief return horizontal offset from anchor point. can be either absolute or proportional
		 */
		float getHorizontalOffset() const { return ox; }
		/**
		 * @brief get layout type
		 */
		int getLayoutType() const { return layoutType; }
		/**
		 * @brief absolute value offset from anchor point
		 */
		void setAbsoluteLayout() {	layoutType = 0;	}
		/**
		 * @brief proportional offset from ancor point
		 */
		void setRelativeLayout() {	layoutType = 1;	}
		/*
		 * @brief specify the object's new position according to anchor, will set offset type to absolute value
		 *
		 * @param _ox horizontal offset
		 * @param _oy vertical offset
		 */
		virtual void moveTo(float _ox, float _oy)
		{
			layoutType = 0;
			ox = _ox;
			oy = _oy;
			/*
			if (true)
			{
				isPositionUpdate = false;
				rect.x2 += x - rect.x1;
				rect.y2 += y - rect.y1;
				rect.x1 = x;
				rect.y1 = y;
			}*/
		}
		/**
		 * @brief calc absolute position according to anchor and offset. might be called recursively
		 */
		void calcAbsolutePosition()
		{
			if (isPositionUpdate) 
			{
				if (anchor) 
				{
					anchor->calcAbsolutePosition();
					// absolute offset
					if (layoutType == 0) _SetRectLTPoint(anchor->rect.x1 + ox, anchor->rect.y1 + oy);
					else 
						_SetRectLTPoint(
							anchor->rect.x1 * (1 - ox) + anchor->rect.x2 * ox,
							anchor->rect.y1 * (1 - oy) + anchor->rect.y2 * oy
							);
				}
				else 
				{
					if (layoutType == 0) _SetRectLTPoint(ox, oy);
					else MessageBox(NULL, L"Proportional to Screen not implemented yet", L"Error", MB_OK);
				}
				isPositionUpdate = false;
			}
		}
		/**
		 * @brief assign a id(for distinguishing this GuiObject) to thi GuiObject, allocated by SceneManager
		 *
		 * @param _id GuiId to be assigned
		 */
		void assignId(int _id) { id = _id; }
		/**
		 * @brief add this gui object to gui through SceneManager
		 *
		 * @param pointer to SceneManager
		 * @param anchorPoint specify the object' s anchor
		 *
		 * @return whether success
		 */
		virtual bool addToGui(SceneManager*, IGuiObject* anchor = NULL);
		virtual ~IGuiObject() {}
		virtual void release() {}
	private:
		/*
		 * @brief set GuiObject 's rect position by specifying the position of its left top point
		 *
		 * @param x horizontal position
		 * @param y vertical position
		 */
		void _SetRectLTPoint(float x, float y)
		{
			rect.x2 += x - rect.x1;
			rect.y2 += y - rect.y1;
			rect.x1 = x;
			rect.y1 = y;
		}
	protected:
		hgeResourceManager* hgeResMan;
		int layoutType;
		/**
		 * @brief ox absolute or proportional horizontal offset from anchor point
		 */
		float ox;
		/**
		 * @brief ox absolute or proportional vertical offset from anchor point
		 */
		float oy;
		/**
		 * @brief current position = anchor.position + offset. null means the GuiObject is placed according to the screen
		 */
		IGuiObject* anchor;
		/**
		 * @brief whether position is changed. if yes, all subordinate guiobject will need to be update
		 */
		bool isPositionUpdate;

	};
}

#endif
